package com.zm.tools.util.core.generatecode.member;

import com.zm.tools.util.core.TableMetadateReadUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * @author zoum
 * @create 2018/9/6 10:57
 */
public class GenerateCodeUtil {

    private TableMetadateReadUtil tableMetadateReadUtil = new TableMetadateReadUtil();

    private String baseFilePath = "E:\\git\\data";

    private final static Logger LOGGER = LoggerFactory.getLogger(GenerateCodeUtil.class);

    public  GenerateCodeUtil(){

    }

    public void generateCode(String appName, String ... tableNames) throws IOException{
        Arrays.stream(tableNames).forEach(tableName -> {
            StringBuilder newTableName = new StringBuilder();
            Arrays.stream(tableName.split("_")).forEach(s -> {
                newTableName.append(StringUtils.isBlank(s) ? "" : StringUtils.capitalize(s));
            });
            try {
                generateModel(newTableName.toString(), appName, "model");
                generateFacade(newTableName.toString(), appName, "facade");
                GenerateManagerCode.generateManager(baseFilePath, newTableName.toString(), appName, "manager", "");

            }catch (IOException e){
                e.printStackTrace();
            }
        });
    }

    private void generateModel(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateModel start for " + tableName);
        String model_vo_path = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\java\\com\\rongzhijia\\member\\model\\vo";
        File model_vo_file  = new File(model_vo_path);
        if (!model_vo_file.exists()){
            model_vo_file.mkdir();
        }
        File vo = new File(model_vo_file.getPath(), tableName+"VO.java");
        if (vo.exists()){
            vo.delete();
        }
        vo.createNewFile();
        String dtoName = tableName + "DTO";
        FileWriter fw = new FileWriter(vo);
        StringBuilder sb = new StringBuilder();
        sb.append("package com.rongzhijia.member.model.vo;\n\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.model.dto." + tableName.toLowerCase() + "." + dtoName + ";\n\n")
                .append("public class " + tableName + "VO extends " + dtoName + " {\n\n")
                .append("}");
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateModel start for " + tableName);
        generateModelConvert(tableName, appName, modelName);


    }

    private void generateModelConvert(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateModelConvert start for " + tableName);
        String model_vo_path = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\java\\com\\rongzhijia\\member\\model\\convert";
        File model_vo_file  = new File(model_vo_path);
        if (!model_vo_file.exists()){
            model_vo_file.mkdir();
        }

        String className = tableName+"Convert.java";
        File classFile = new File(model_vo_file.getPath(), className);
        if (classFile.exists()){
            classFile.delete();
        }
        classFile.createNewFile();
        String dtoName = tableName + "DTO";
        String voName = tableName + "VO";
        FileWriter fw = new FileWriter(classFile);
        StringBuilder sb = new StringBuilder();
        sb.append("package com.rongzhijia.member.model.convert;\n\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.model.dto." + tableName.toLowerCase() + "." + dtoName + ";\n")
                .append("import com.rongzhijia.member.model.vo." + voName + ";\n")
                .append("import org.springframework.beans.BeanUtils;\n")
                .append("import java.util.ArrayList;\n")
                .append("import java.util.List;\n\n")
                .append("public class " + className.split("\\.")[0] + " {\n\n")
                .append("   public static " + dtoName + " toDTO("+ voName +" src" +"){\n")
                .append("       if(src == null){\n")
                .append("           return null;\n")
                .append("       }\n")
                .append("       "+dtoName + " target = new " + dtoName + "();\n")
                .append("       BeanUtils.copyProperties(src, target);\n")
                .append("       return target;\n")
                .append("   }\n")
                .append("   public static " + voName + " toVO("+ dtoName +" src" +"){\n")
                .append("       if(src == null){\n")
                .append("           return null;\n")
                .append("       }\n")
                .append("       "+voName + " target = new " + voName + "();\n")
                .append("       BeanUtils.copyProperties(src, target);\n")
                .append("       return target;\n")
                .append("   }\n")
                .append("   public static List<" + voName + "> toVOS(List<"+ dtoName +"> src" +"){\n")
                .append("       if(src == null || src.isEmpty()){\n")
                .append("           return null;\n")
                .append("       }\n")
                .append("       List<"+voName + "> target = new ArrayList<>();\n")
                .append("       src.forEach(dto -> target.add(toVO(dto)));\n")
                .append("       return target;\n")
                .append("   }\n")
                .append("}");
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateModelConvert start for " + tableName);
    }

    private void generateController(String tableName){
        List<String>columns = tableMetadateReadUtil.getColumns(tableName);
    }

    private void generateFacade(String tableName, String appName, String modelName) throws IOException{
        generateFacade4Read(tableName, appName, "facade");
        generateFacade4Write(tableName, appName, "facade");
        generateDubboXML(tableName, appName, modelName);
    }

    private void generateFacade4Write(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateFacade4Write start for " + tableName);
        String readOrWrite = "write";
        String parentPath = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\java\\com\\rongzhijia\\member\\facade\\" + readOrWrite;
        File parentFile  = new File(parentPath);
        if (!parentFile.exists()){
            parentFile.mkdir();
        }
        String className = tableName + StringUtils.capitalize(readOrWrite) + "Facade.java";
        File classFile = new File(parentFile.getPath(), className);
        if (classFile.exists()){
            classFile.delete();
        }
        classFile.createNewFile();
        String dtoName = tableName + "DTO";
        String dtoInstanceName = String.valueOf(dtoName.charAt(0)).toLowerCase() + dtoName.substring(1);
        String serviceName = tableName + StringUtils.capitalize(readOrWrite) + "Service";
        String serviceInstanceName = String.valueOf(serviceName.charAt(0)).toLowerCase() + serviceName.substring(1);
        FileWriter fw = new FileWriter(classFile);
        StringBuilder sb = new StringBuilder();
        sb.append("package com.rongzhijia.member.facade." + readOrWrite + ";\n\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.model.dto." + tableName.toLowerCase() + "." + dtoName + ";\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.api."+ readOrWrite +"." + serviceName + ";\n\n")
                .append("import org.springframework.beans.factory.annotation.Autowired;\n")
                .append("import org.springframework.stereotype.Component;\n\n")
                .append("import java.util.Date;\n\n")
                .append("@Component\n")
                .append("public class " + className.split("\\.")[0] + " {\n\n")
                .append("   @Autowired\n")
                .append("   private " + serviceName + " " + serviceInstanceName + ";\n\n")
                .append("   public int add( " + dtoName + " " + dtoInstanceName + "){\n")
                .append("       Date date = new Date();\n")
                .append("       "+ dtoInstanceName + ".setCreateTime(date);\n")
                .append("       "+ dtoInstanceName + ".setUpdateTime(date);\n")
                .append("       return " + serviceInstanceName + ".insert"+ tableName + "Service(" + dtoInstanceName + ");\n")
                .append("   }\n\n")
                .append("   public int update( " + dtoName + " " + dtoInstanceName + "){\n")
                .append("       Date date = new Date();\n")
                .append("       "+ dtoInstanceName + ".setUpdateTime(date);\n")
                .append("       return " + serviceInstanceName + ".update"+ tableName + "Service(" + dtoInstanceName + ");\n")
                .append("   }\n")
                .append("   public int delete( " + dtoName + " " + dtoInstanceName + "){\n")
                .append("       return " + serviceInstanceName + ".delete"+ tableName + "Service(" + dtoInstanceName + ");\n")
                .append("   }\n")
                .append("}");
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateFacade4Write end for " + tableName);
    }

    private void generateDubboXML(String tableName, String appName, String modelName) throws IOException{
        generateWriteDubboXML(tableName, appName, modelName);
        generateReadDubboXML(tableName, appName, modelName);
    }

    private void generateWriteDubboXML(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateFacade4Write start for " + tableName);
        String readOrWrite = "write";
        String parentPath = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\resources\\dubbo";
        File parentFile  = new File(parentPath);
        if (!parentFile.exists()){
            parentFile.mkdir();
        }
        String className = "dubbo-consumer-" + tableName + "-" + readOrWrite + ".xml";
        File classFile = new File(parentFile.getPath(), className);
        if (classFile.exists()){
            classFile.delete();
        }
        classFile.createNewFile();
        String serviceName = tableName + StringUtils.capitalize(readOrWrite) + "Service";
        String serviceInstanceName = String.valueOf(serviceName.charAt(0)).toLowerCase() + serviceName.substring(1);
        FileWriter fw = new FileWriter(classFile);
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
                .append("<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
                .append("   xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n")
                .append("   xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n")
                .append("       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd\n")
                .append("       http://code.alibabatech.com/schema/dubbo\n")
                .append("       http://code.alibabatech.com/schema/dubbo/dubbo.xsd\"\n")
                .append("       default-autowire=\"byName\" default-lazy-init=\"false\">\n")
                .append("   <dubbo:reference interface=\"com.rongzhijia.jiedianqian.basic.member.api."+ readOrWrite +"."+ serviceName +"\" id=\""+ serviceInstanceName +"\" check=\"false\"/>\n")
                .append("</beans>\n")
                ;
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateFacade4Write end for " + tableName);
    }

    private void generateReadDubboXML(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateFacade4Write start for " + tableName);
        String readOrWrite = "read";
        String parentPath = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\resources\\dubbo";
        File parentFile  = new File(parentPath);
        if (!parentFile.exists()){
            parentFile.mkdir();
        }
        String className = "dubbo-consumer-" + tableName + "-" + readOrWrite + ".xml";
        File classFile = new File(parentFile.getPath(), className);
        if (classFile.exists()){
            classFile.delete();
        }
        classFile.createNewFile();
        String serviceName = tableName + StringUtils.capitalize(readOrWrite) + "Service";
        String serviceInstanceName = String.valueOf(serviceName.charAt(0)).toLowerCase() + serviceName.substring(1);
        FileWriter fw = new FileWriter(classFile);
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
                .append("<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
                .append("   xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n")
                .append("   xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n")
                .append("       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd\n")
                .append("       http://code.alibabatech.com/schema/dubbo\n")
                .append("       http://code.alibabatech.com/schema/dubbo/dubbo.xsd\"\n")
                .append("       default-autowire=\"byName\" default-lazy-init=\"false\">\n")
                .append("   <dubbo:reference interface=\"com.rongzhijia.jiedianqian.basic.member.api." + readOrWrite +"."+ serviceName +"\" id=\""+ serviceInstanceName +"\" check=\"false\"/>\n")
                .append("</beans>\n")
                ;
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateFacade4Write end for " + tableName);
    }

    private void generateFacade4Read(String tableName, String appName, String modelName) throws IOException{
        LOGGER.info("generateFacade4Read start for " + tableName);
        String readOrWrite = "read";
        String parentPath = baseFilePath + "\\" + appName + "\\"+ appName + "-" + modelName +"\\src\\main\\java\\com\\rongzhijia\\member\\facade\\" + readOrWrite;
        File parentFile  = new File(parentPath);
        if (!parentFile.exists()){
            parentFile.mkdir();
        }
        String className = tableName + StringUtils.capitalize(readOrWrite) + "Facade.java";
        File classFile = new File(parentFile.getPath(), className);
        if (classFile.exists()){
            classFile.delete();
        }
        classFile.createNewFile();
        String dtoName = tableName + "DTO";
        String dtoInstanceName = String.valueOf(dtoName.charAt(0)).toLowerCase() + dtoName.substring(1);
        String serviceName = tableName + StringUtils.capitalize(readOrWrite) + "Service";
        String serviceInstanceName = String.valueOf(serviceName.charAt(0)).toLowerCase() + serviceName.substring(1);
        FileWriter fw = new FileWriter(classFile);
        StringBuilder sb = new StringBuilder();
        sb.append("package com.rongzhijia.member.facade." + readOrWrite + ";\n\n")
                .append("import com.rongzhijia.jdq.core.common.PageResult;\n")
                .append("import com.rongzhijia.jdq.core.orm.Pagination;\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.model.dto." + tableName.toLowerCase() + "." + dtoName + ";\n")
                .append("import com.rongzhijia.jiedianqian.basic.member.api."+ readOrWrite +"." + serviceName + ";\n\n")
                .append("import org.springframework.beans.factory.annotation.Autowired;\n")
                .append("import org.springframework.stereotype.Component;\n\n")
                .append("import java.util.List;\n\n")
                .append("@Component\n")
                .append("public class " + className.split("\\.")[0] + " {\n\n")
                .append("   @Autowired\n")
                .append("   private " + serviceName + " " + serviceInstanceName + ";\n\n")
                .append("   public "+ dtoName + " get"+ tableName + "Service(" + dtoName + " " + dtoInstanceName + "){\n")
                .append("       return " + serviceInstanceName + ".get"+ tableName + "Service(" + dtoInstanceName + ");\n")
                .append("   }\n\n")
                .append("   public List<" + dtoName + "> query" + tableName + "Service(" + dtoName + " " + dtoInstanceName + "){\n")
                .append("       return " + serviceInstanceName + ".query"+ tableName + "Service(" + dtoInstanceName + ");\n")
                .append("   }\n\n")
                .append("   public List<" + dtoName + "> query" + tableName + "Service(" + dtoName + " " + dtoInstanceName + ", Pagination pagination){\n")
                .append("       PageResult<" + dtoName + "> " + dtoInstanceName + "Page = this.select" + tableName + "PageService(" + dtoInstanceName + ", pagination);\n")
                .append("       if("+ dtoInstanceName + "Page != null && "+ dtoInstanceName +"Page.getList() != null){\n")
                .append("           return "+ dtoInstanceName +"Page.getList();\n")
                .append("       }\n")
                .append("       return null;\n")
                .append("   }\n\n")
                .append("   public PageResult<" + dtoName + "> select" + tableName + "PageService(" + dtoName + " " + dtoInstanceName + ", Pagination pagination){\n")
                .append("       if (pagination != null){\n")
                .append("            pagination.setLimitStart((pagination.getPageNo()-1)*pagination.getPageSize());\n")
                .append("       }\n")
                .append("       return " + serviceInstanceName + ".select"+ tableName + "PageService(" + dtoInstanceName + ", pagination);\n")
                .append("   }\n\n")
                .append("}");
        fw.write(sb.toString());
        fw.flush();
        fw.close();
        LOGGER.info("generateFacade4Read start for " + tableName);
    }

    public static void main(String[] args) throws Exception{
        new GenerateCodeUtil().generateCode("back-member", "mobile_recharge_order");
    }
}
